Skip to content

feat: model-based routing — wildcard model-to-provider mapping in proxy#277

Open
zhangyang-crazy-one wants to merge 1 commit into
SaladDay:mainfrom
zhangyang-crazy-one:feat/model-based-routing-pr
Open

feat: model-based routing — wildcard model-to-provider mapping in proxy#277
zhangyang-crazy-one wants to merge 1 commit into
SaladDay:mainfrom
zhangyang-crazy-one:feat/model-based-routing-pr

Conversation

@zhangyang-crazy-one

@zhangyang-crazy-one zhangyang-crazy-one commented Jun 12, 2026

Copy link
Copy Markdown

Summary

实现基于模型名称的路由功能:通过通配符模式(如 *sonnet*claude-*)将不同的模型请求路由到指定的 provider。

核心功能

数据库 (Phase 1)

  • model_routes 表:存储模型模式到 provider 的映射,支持优先级排序
  • 完整 CRUD DAO,含外键约束和级联删除

路由引擎 (Phase 2)

  • ModelRouter:通配符 * 转正则匹配,大小写不敏感,按优先级选择
  • 集成到 proxy pipeline,模型路由优先于 failover 队列
  • 命中追踪(hit_count / last_hit_at)

CLI 命令 (Phase 3)

  • cc-switch proxy model-route list|add|remove|toggle|update
  • 表格化输出,支持跨 app type 隔离

TUI 管理界面 (Phase 4)

  • Settings → Model Routes 页面,含 add/edit/delete/toggle 操作
  • 3 步 overlay 向导(Pattern → Provider → Priority)
  • Dashboard 多色路由命中图例

Bug 修复(Codex review)

  • P1: 模型路由命中不再静默切换当前 provider(加 is_model_routed 标记)
  • P2: 通配符模式加 ^ 锚定,防止前缀越界匹配(如 claude-* 匹配 xclaude-opus
  • P3: TUI 编辑保留 disabled 状态,不再静默恢复已禁用的路由

CI 状态

  • ✅ cargo fmt --check
  • ✅ cargo clippy -- -D warnings
  • ✅ cargo test: 2641 passed, 1 pre-existing failure

架构对齐

  • schema 与上游 cc-switch v12 对齐(TEXT PRIMARY KEY + UUID v4)
  • 前向兼容 v12 数据库版本检测

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3fe23b460

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

)
.await
{
Ok(Some((_route_id, provider))) => (vec![provider], Some("model_route".to_string())),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid syncing model-routed providers as current

When a model route matches, this replaces the provider list with only the route target, but the later success path still builds SuccessSyncInfo and calls ProxyServerState::sync_successful_provider_selection, which persists set_current_provider and may update the live backup whenever the route target differs from current_provider_id_at_start. In a setup where *sonnet* routes to provider B while the user’s current provider is A, the first successful routed request permanently switches the app to B, so subsequent non-routed traffic and live config no longer use the user-selected provider.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/proxy/model_router.rs Outdated
Comment on lines +134 to +142
let mut regex_str = String::from("(?i)");
for (i, segment) in segments.iter().enumerate() {
if i > 0 {
regex_str.push_str(".*");
}
regex_str.push_str(&regex::escape(segment));
}

Regex::new(&regex_str)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Anchor wildcard model route patterns

Wildcard patterns are compiled without ^...$, so regex matching can succeed on any substring rather than the whole model id. For example, a user adding the documented prefix route claude-* would also match xclaude-opus, and sonnet* would match claude-sonnet even though no leading wildcard was supplied; this makes route precedence unpredictable when model ids merely contain another route’s prefix.

Useful? React with 👍 / 👎.

pattern,
provider_id,
priority,
enabled: true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve enabled state when editing routes

The TUI edit flow always sends enabled: true to update_model_route, so editing a disabled model route’s pattern/provider/priority silently re-enables it. This differs from the CLI update path, which preserves existing.enabled, and it can cause a route the user intentionally disabled to start matching requests again after a harmless edit.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one zhangyang-crazy-one changed the title feat: per-provider color dot matrix in proxy dashboard feat: model-based routing — wildcard model-to-provider mapping in proxy Jun 12, 2026
@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4e55a75d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +104 to +109
json!({
"id": id,
"object": "model",
"created": 1700000000,
"owned_by": "cc-switch"
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return Anthropic model fields for Claude /v1/models

When Claude Code is pointed at this proxy via ANTHROPIC_BASE_URL, its /model flow uses Anthropic's GET /v1/models schema; the Anthropic Models API documents each item with fields like type, display_name, and created_at (plus pagination fields). This handler only emits OpenAI-style entries (object, created, owned_by), so Anthropic clients that deserialize or display ModelInfo can reject the response or show no usable models even though routes exist. Consider emitting the Anthropic fields as well, or a protocol superset.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05861bcea0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/proxy/handler_context.rs Outdated
Comment on lines +53 to +56
let request_model = body
.get("model")
.and_then(|value| value.as_str())
.unwrap_or("unknown")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Extract Gemini route models from the request URI

For standard Gemini proxy calls, the model is in the path (for example /v1beta/models/gemini-2.5-pro:generateContent) rather than in the JSON body, so this always sets request_model to unknown for those requests. Since model-route matching now uses this value before falling back to ProviderRouter, any --app gemini model route created through the new CLI/TUI will never match normal Gemini traffic.

Useful? React with 👍 / 👎.

self.overlay = Overlay::TextInput(TextInputState {
title: texts::tui_model_route_add_priority_title().to_string(),
prompt: texts::tui_model_route_add_priority_prompt().to_string(),
input: TextInput::new("0".to_string()),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve priority when editing model routes

When editing an existing route in the TUI, the priority prompt is always prefilled with 0, so accepting the default after changing only the pattern/provider silently rewrites any non-zero priority to highest priority. That changes routing order for existing rules even though the user did not intend to edit priority; the edit flow should prefill or preserve the route's current priority.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/database/schema.rs Outdated
Comment on lines +376 to +379
if version == 12 {
log::warn!("数据库版本 {version} 高于 SCHEMA_VERSION={SCHEMA_VERSION},跳过迁移(兼容模式)");
conn.execute("RELEASE schema_migration;", []).ok();
return Ok(());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run v12 compatibility repairs before returning

This compatibility branch accepts user_version=12 and returns before running the column repairs that this patch relies on for model_routes. If a v12 database already has model_routes but lacks hit_count/last_hit_at (the code comments call out that case), create_tables will not alter the existing table and later list_model_routes SELECTs those columns, causing proxy/TUI/CLI model-route operations to fail with no such column.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a45cc8b5b0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/database/schema.rs Outdated
Comment on lines +378 to +380
if version == 12 {
log::warn!("数据库版本 {version} 高于 SCHEMA_VERSION={SCHEMA_VERSION},进入兼容模式并补齐列");
Self::create_tables_on_conn(conn)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Repair v12 model_routes columns before returning

When opening a database with user_version 12, this compatibility branch returns after create_tables_on_conn, but CREATE TABLE IF NOT EXISTS does not alter an existing upstream model_routes table. The new DAO selects hit_count and last_hit_at, so a v12 database whose table lacks those local tracking columns will make model-route list/TUI/proxy lookups fail with no such column instead of running in compatibility mode. Run the same add_column_if_missing repairs here before returning.

Useful? React with 👍 / 👎.

self.overlay = Overlay::ModelRouteProviderPicker {
pattern: raw,

selected: 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preselect the existing provider when editing

When editing an existing rule, the provider picker is always initialized at index 0. If the user only changes or accepts the pattern and presses Enter through the provider step, handle_model_route_provider_picker_key uses that selected row as the provider, so the route is silently moved to the first provider instead of preserving its current target. Initialize selected from the route's current provider_id before opening the picker.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one zhangyang-crazy-one force-pushed the feat/model-based-routing-pr branch from 39675ac to 20feb74 Compare June 15, 2026 11:33
@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20feb74877

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

regex_str.push_str(&regex::escape(segment));
}

Regex::new(&regex_str)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Anchor wildcard routes that should match suffixes

For wildcard patterns that do not end in *, the generated regex is only start-anchored, so a rule such as *-4-5 also matches claude-haiku-4-55 because is_match can stop at the -4-5 prefix. Since the first matching route selects a single provider, suffix-style rules can route newer/different model IDs to the wrong provider; append $ when the pattern itself does not end with *.

Useful? React with 👍 / 👎.

self.overlay = Overlay::ModelRouteProviderPicker {
pattern: raw,

selected: 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Initialize edit picker to the current provider

When editing an existing route, the provider picker always starts at index 0, so pressing Enter to keep the provider silently changes the route to the first provider whenever the current provider is not first in data.providers.rows. Seed selected from the existing route's provider_id so editing pattern/priority does not rewrite the provider unintentionally.

Useful? React with 👍 / 👎.

zhangyang-crazy-one pushed a commit to zhangyang-crazy-one/cc-switch-cli that referenced this pull request Jun 16, 2026
…Day#10/SaladDay#11

Dashboard multi-provider wave color:
- observe_proxy_provider_activity no longer silently returns on the
  first tick, so provider samples align with main input/output samples
  from the start; resync provider samples after a proxy restart resets
  the main counter, fixing the wave degrading to a single accent color

Codex review (PR SaladDay#277):
- proxy: anchor non-trailing-* model route patterns at the end ($) so a
  suffix rule like "*-4-5" no longer matches "claude-haiku-4-55"; use
  "*sonnet*" to match a substring anywhere
- tui: preselect the current provider when editing a model route so
  Enter does not silently move the route to the first provider
@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c542b4a12a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +167 to +168
ModelRouteCommand::Remove { id } => {
state.db.delete_model_route(&id)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope route mutations to the selected app

When a route id from another app is supplied, this deletes it solely by id even though the command is executed under the currently selected --app; the toggle and update paths use the same unscoped id-only DAO calls. Since list/add are app-scoped, a user can accidentally remove or modify a Codex route while running --app claude; verify the existing route's app_type matches app or use app-scoped DAO mutations before changing it.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/proxy/handlers.rs Outdated
Comment on lines +89 to +94
let standard_models = match pattern_lower.as_str() {
"*haiku*" | "haiku" => vec!["claude-haiku-4-5-20251001"],
"*sonnet*" | "sonnet" => vec!["claude-sonnet-4-6"],
"*opus*" | "opus" => vec!["claude-opus-4-8"],
_ => Vec::new(),
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Include exact route patterns in the model list

For an exact model route such as gpt-5 or deepseek-v4-pro, this match falls through to _ and adds nothing to /v1/models, so clients that populate model pickers from the proxy can miss configured route-only models or see an empty list when providers do not define env model mappings. Exact patterns without * should be emitted as model ids in addition to the role shortcuts.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e9132db64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/proxy/handlers.rs Outdated
/// clients can consume the response.
pub async fn handle_models(State(state): State<ProxyServerState>) -> impl IntoResponse {
let db = state.db;
let app_type = "claude";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Select models for the requesting app

When an OpenAI/Codex client calls the newly registered GET /v1/models endpoint, this hard-coded app scope means the response is built from Claude providers and Claude model routes only; Codex/Gemini model routes created with --app codex or --app gemini will never appear in model discovery even though request routing uses those app-specific routes. I checked server.rs, and this handler is the only /v1/models route, so the app context needs to be passed/inferred instead of fixed to Claude.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/cli/commands/proxy.rs Outdated
Comment on lines +40 to +41
#[arg(long)]
provider_id: Option<String>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept the documented --provider flag

The new command docs/requirements describe model-route update <id> ... [--provider], but with #[arg(long)] on the provider_id field Clap exposes the flag as the case-converted field name (--provider-id; Clap derive reference: https://docs.rs/clap/latest/clap/_derive/index.html#arg-attributes). Users following the documented --provider form will get an unknown-argument error when trying to move a route to a different provider, so add long = "provider" or an alias.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one

Copy link
Copy Markdown
Author

Re: codex review #7 (/v1/models app scope) and #8 (--provider flag)

#8 — fixed in 68d4307: model-route update now exposes --provider (matching the docs) instead of the Clap-derived --provider-id.

#7 — by design, not a defect. The GET /v1/models handler emits the Anthropic Models API schema (type, display_name, created_at) and serves Claude Code clients reached via ANTHROPIC_BASE_URL. Codex traffic is routed through /v1/responses (/codex/v1/responses) and Gemini through /v1beta/models; neither consumes /v1/models for model discovery. Scoping this endpoint to Claude is the current intended behavior, so hard-coding app_type = "claude" here is correct for now. Multi-app /v1/models discovery can be tracked as a follow-up if a Codex/Gemini client is found to depend on it.

@SaladDay

Copy link
Copy Markdown
Owner

Hi @zhangyang-crazy-one, thanks a lot for this PR — it's thorough work, covering all four phases from the database through to the TUI, with the tests and Codex review followed up closely. You clearly put real care into it 👍

I noticed Phase 1 touches the database schema (the new model_routes table, bumping SCHEMA_VERSION to 11, the migration, plus the hit_count / last_hit_at columns). Schema changes are basically irreversible once users upgrade, and Codex flagged the v12 compatibility branch a few times, so I'd like to align on the approach with you before we merge — mainly around how the version number maps to upstream cc-switch, the table design for the tracking fields, and migration compatibility.

How about we chat through the design first (either here in the comments or in a new issue)? Pinning it down before pushing the code further will keep things on a steadier footing. The routing engine, CLI, and TUI parts all look like they're heading in a good direction — it's really just the schema layer I'd like to firm up first. Thanks again 🙏

@zhangyang-crazy-one

Copy link
Copy Markdown
Author

Thanks for the thorough review @SaladDay! Completely agree the schema layer should be pinned down before merge.

On SCHEMA_VERSION — the current PR bumps it to 12 for the model_routes migration, but I'd rather coordinate with upstream than unilaterally take a version slot. Do you have a near-term plan to bump the version yourself? If not (or if you'd prefer to keep v11 as the ceiling for now), I can drop the migration step entirely and let create_tables_on_conn handle the model_routes table via CREATE TABLE IF NOT EXISTS + add_column_if_missing on every open. That's transparent for existing databases and needs no version bump at all — the table just appears on next startup.

On the tracking fields (hit_count, last_hit_at) — they're lightweight dashboard statistics for the TUI route-hit display. They don't affect the routing engine itself. Happy to strip them if you'd rather keep the table minimal, or keep them if the cost is negligible.

Let me know which direction you prefer and I'll update the PR accordingly. The routing / CLI / TUI parts can wait — schema first, then rebase. Thanks again!

zhangyang-crazy-one added a commit to zhangyang-crazy-one/cc-switch-cli that referenced this pull request Jun 22, 2026
The /v1/models discovery endpoint hardcoded app_type to "claude", so Codex/Gemini clients calling it never saw their own app's model routes or provider env models. Iterate AppType::all() and merge provider env models plus enabled routes from every app, so the endpoint is useful regardless of which client consumes it. Addresses Codex review P2 on PR SaladDay#277.
@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13f88f0413

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/proxy/handler_context.rs Outdated
.and_then(|value| value.as_str())
.map(|s| s.to_string())
.or_else(|| extract_gemini_model_from_path(path))
.unwrap_or_else(|| "unknown".to_string());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid routing model-less requests as unknown

When a request has no model field/path model, this sentinel is still passed into ModelRouter; a catch-all route such as * matches "unknown". That changes model-less endpoints like Codex /v1/responses/compact (the existing passthrough test sends only input) from using the current provider to being forced through the catch-all route, even though there is no model to route on. Keep the model as optional for routing, or skip model-route lookup when extraction fails.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/proxy/server.rs Outdated
if takeover_enabled {
ProxyService::new(self.db.clone())
.refresh_failover_live_snapshot_for_provider(app_type.as_str(), provider)
.update_live_backup_from_provider(app_type.as_str(), provider)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the original takeover live backup

When automatic failover succeeds while proxy takeover is active, this now overwrites proxy_live_backup with the failover provider. That backup is later restored verbatim by restore_live_config_for_app when takeover is disabled or recovered, so the user's original live config captured at takeover start is lost; the hot-switch path still avoids this by writing a failover live snapshot instead. Refresh/write the failover snapshot here rather than mutating the live backup.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@zhangyang-crazy-one

Copy link
Copy Markdown
Author

@codex review this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6349a2c298

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +918 to +919
None => Action::None,
},
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore cargo fmt compliance

Running cargo fmt --check under src-tauri/ fails on this match arm because rustfmt expects a trailing comma after the KeyCode::Enter arm body. The repository guidance notes CI runs cargo fmt --check for src-tauri/**, so this formatting miss will block the PR even though the code otherwise parses.

Useful? React with 👍 / 👎.

@zhangyang-crazy-one zhangyang-crazy-one force-pushed the feat/model-based-routing-pr branch 4 times, most recently from 8ffc549 to 1f5390c Compare July 8, 2026 01:41
实现基于模型名称的路由功能:通过通配符模式将不同的模型请求路由到指定的 provider。

核心功能:
- model_routes 表 + 完整 CRUD DAO(含外键级联删除)
- ModelRouter:通配符 * 转正则匹配,大小写不敏感,按优先级选择
- CLI:proxy model-route list|add|remove|toggle|update
- TUI:Settings → Model Routes 页面 + Dashboard 多色路由命中图例

Bug 修复:
- 模型路由命中不静默切换当前 provider(加 is_model_routed 标记)
- 通配符模式加 ^ 锚定,防止前缀越界匹配
- TUI 编辑保留 disabled 状态
@zhangyang-crazy-one zhangyang-crazy-one force-pushed the feat/model-based-routing-pr branch from 1f5390c to f037daf Compare July 8, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants